package com.yeebo.admin.domain;

import cn.hutool.core.bean.BeanUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.yeebo.admin.dao.SysResourceDao;
import com.yeebo.admin.dao.SysRoleDao;
import com.yeebo.admin.dao.SysUserDao;
import com.yeebo.admin.dao.SysUserRoleDao;
import com.yeebo.constants.Constants;
import com.yeebo.enums.ResultCode;
import com.yeebo.enums.admin.SysUserStatusEnums;
import com.yeebo.exception.ServiceException;
import com.yeebo.model.admin.SysResource;
import com.yeebo.model.admin.SysRole;
import com.yeebo.model.admin.SysUser;
import com.yeebo.model.admin.SysUserRole;
import com.yeebo.utils.MD5Utils;
import com.yeebo.vo.admin.SysUserManageVO;
import com.yeebo.vo.admin.SysUserRolesVO;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Component("sysUserDomain")
public class SysUserDomain {

    @Resource
    private SysUserDao sysUserDao;
    @Resource
    private SysRoleDao sysRoleDao;
    @Resource
    private SysResourceDao sysResourceDao;
    @Resource
    private SysUserRoleDao sysUserRoleDao;

    public SysUser checkUserAndPassword(String loginName, String password) {
        // 1、获取Subject实例对象
        Subject currentUser = SecurityUtils.getSubject();
        // 2、将用户名和密码封装到UsernamePasswordToken
        UsernamePasswordToken token = new UsernamePasswordToken(loginName, password);
        // 3、认证
        try {
            currentUser.login(token); // 传到MyShiroRealm类中的认证方法
        } catch (UnknownAccountException e) {
            throw new ServiceException(ResultCode.SYS_USER_NOT_EXIST);
        } catch (IncorrectCredentialsException e) {
            throw new ServiceException(ResultCode.SYS_PASSWORD_NOT_MATCH);
        } catch (AuthenticationException e) {
            throw new ServiceException(ResultCode.SYS_PASSWORD_NOT_MATCH);
        }

        return sysUserDao.findByLoginName(loginName);
    }

    public void updateLoginInfo(SysUser existUser, String ipAddress) {
        existUser.setLastLoginTime(new Date());
        existUser.setLastLoginIp(ipAddress);
        sysUserDao.update(existUser);
    }

    public SysUser getUserById(Long userId) {
        return sysUserDao.getByUserId(userId);
    }

    public List<SysRole> loadRolesByUserId(Long sysUserId) {
        return sysRoleDao.loadRolesByUserId(sysUserId);
    }

    public SysUser getUserByLoginName(String loginName) {
        return sysUserDao.findByLoginName(loginName);
    }

    public List<SysResource> loadResourcesByUserId(Long userId) {
        return sysResourceDao.loadResourcesByUserId(userId);
    }

    public Page<SysUserManageVO> loadSysUserList(Integer pageNo, Integer pageSize, String filterUsername) {
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("filterUsername", filterUsername);
        PageHelper.startPage(pageNo, pageSize);
        Page<SysUser> sysUserPage = sysUserDao.loadSysUserList(queryMap);
        Page<SysUserManageVO> sysUserManageVOPage = new Page<>();
        BeanUtil.copyProperties(sysUserPage, sysUserManageVOPage);

        List<SysUser> originalList = sysUserPage.getResult();
        for (SysUser sysUser : originalList) {
            SysUserManageVO targetVo = new SysUserManageVO();
            BeanUtil.copyProperties(sysUser, targetVo);
            targetVo.setStatusStr(SysUserStatusEnums.getDescByStatus(sysUser.getStatus()));
            sysUserManageVOPage.add(targetVo);
        }
        return sysUserManageVOPage;
    }

    public SysUserManageVO getSysUserInfoById(Long userId) {
        SysUser sysUser = sysUserDao.getByUserId(userId);

        SysUserManageVO targetVo = new SysUserManageVO();
        BeanUtil.copyProperties(sysUser, targetVo);
        targetVo.setStatusStr(SysUserStatusEnums.getDescByStatus(sysUser.getStatus()));

        return targetVo;
    }

    public void addSysUser(String loginName, String username, String phone) {
        Date now = new Date();
        SysUser sysUser = new SysUser();
        sysUser.setLoginName(loginName);
        sysUser.setUsername(username);
        sysUser.setPassword(MD5Utils.MD5(Constants.SYS_USER_DEFAULT_PASSWORD));
        sysUser.setPhone(phone);
        sysUser.setStatus(SysUserStatusEnums.NORMAL.getStatus());
        sysUser.setValid(true);
        sysUser.setCreatedTime(now);
        sysUser.setUpdatedTime(now);
        sysUserDao.add(sysUser);
    }

    public void updateSysUser(SysUser updateEntity) {
        sysUserDao.update(updateEntity);
    }

    public List<SysUserRolesVO> loadSysRoleListByUserId(Long userId) {
        List<SysRole> allValidRoles = sysRoleDao.loadAllValidRoles();
        List<SysRole> currentHaveRoles = sysRoleDao.loadRolesByUserId(userId);

        List<SysUserRolesVO> resultList = new LinkedList<>();
        for (SysRole originalRole : allValidRoles) {
            Long matchCount = currentHaveRoles.stream().filter(s -> s.getId().equals(originalRole.getId())).count();

            SysUserRolesVO targetRole = new SysUserRolesVO();
            BeanUtil.copyProperties(originalRole, targetRole);
            targetRole.setRoleId(originalRole.getId());
            targetRole.setUserId(userId);
            targetRole.setChecked(matchCount > 0 ? true : false);
            resultList.add(targetRole);
        }
        return resultList;
    }

    @Transactional
    public void assignRolesToUser(Long userId, List<SysUserRole> sysUserRoles) {
        // 删除之前的角色
        sysUserRoleDao.deleteSysUserRolesByUserId(userId);
        // 分配新角色
        sysUserRoleDao.batchSave(sysUserRoles);
    }

}
